package cn.xhh.dailyreview.server.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.StringUtils;

public class Utility {
	
	private static final Logger logger = Logger.getLogger(Utility.class.getName());
	
	/** length of the confirmation string to generate */
	private static final int CONFIRM_STRING_LENGTH = 20;
	
	/** characters that confirmation string choose from */
	private static final char[] CONFIRM_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 
		'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
	};

	private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-M-d");

	private static final String REG_EXP_EMAIL = "[\\w.]+@\\w{1,64}\\.[a-zA-Z]{2,6}"; // TODO more precise

	private static final String MAIL_FROM = "from.cooky@gmail.com";
	private static final String MAIL_FROM_NAME = "DailyReview Team";

	/**
	 * Encrypt the input string with MD5 algorithm.
	 * @param input the string to be encrypted
	 * @return the encrypting result
	 */
	public static String md5Digest(String input) {
		String algorithm = "MD5"; 
		try {
			return stringDigest(input, algorithm);
		} catch (NoSuchAlgorithmException e) {
			logger.severe("Initializing MessageDigest failed due to invaid algorithm: " 
					+ algorithm + ". Exception message: " + e.getMessage());
			return null;
		}
	}
	
	/**
	 * Encrypt the input string with SHA algorithm.
	 * @param input the string to be encrypted
	 * @return the encrypting result
	 */
	public static String shaDigest(String input) {
		String algorithm = "SHA"; 
		try {
			return stringDigest(input, algorithm);
		} catch (NoSuchAlgorithmException e) {
			logger.severe("Initializing MessageDigest failed due to invaid algorithm: " + algorithm + 
					". Exception message: " + e.getMessage());
			return null;
		}
	}

	/**
	 * Encrypt the input string with the given algorithm.
	 * @param input the string to be encrypted
	 * @return the encrypting result
	 */
	public static String stringDigest(String input, String algorithm) throws NoSuchAlgorithmException {
		if (input == null) return null;
		if (algorithm == null) throw new NoSuchAlgorithmException("Argument algorithm could not be null");
		MessageDigest md = null;
		md = MessageDigest.getInstance(algorithm);
		md.update(input.getBytes());
		byte[] msgDigest = md.digest();
		StringBuffer hexStrBuf = new StringBuffer(msgDigest.length);
		for (byte b : msgDigest) {
			String hex = Integer.toHexString(0xFF & b);
			if (hex.length() == 1) hexStrBuf.append('0');
			hexStrBuf.append(hex);
		}
		return hexStrBuf.toString();
	}

	/**
	 * Generate a random string as an identity , which is used in the link of an email 
	 * for the user to confirm his registration.
	 */
	public static String genConfirmString() {
		StringBuffer sb = new StringBuffer(); // the string generated
		
		for (int i=0; i<CONFIRM_STRING_LENGTH; i++)
			sb.append(CONFIRM_CHARS[(int) (CONFIRM_CHARS.length * Math.random())]);
		
		return sb.toString();
	}
	
	public static void sendMail(String toEmail, String subject, String msgBody)
			throws MessagingException, UnsupportedEncodingException {
		Session session = Session.getDefaultInstance(new Properties());
		Message msg = new MimeMessage(session);
		msg.setFrom(new InternetAddress(MAIL_FROM, MAIL_FROM_NAME));
		msg.addRecipient(RecipientType.TO, new InternetAddress(toEmail));
		msg.setSubject(subject);
		msg.setText(msgBody);
		Transport.send(msg);
		
		// FIXME printing mail
		System.out.println("\n---------- Sending mail -------------");
		System.out.println("Subject: " + subject);
		System.out.println("Body: ");
		System.out.println(msgBody);
		System.out.println("------------------------------------\n");
	}
	
	public static String buildLog(String summary, Exception e) {
		return summary + (e==null ? "" : (" ["+e.getClass().getSimpleName()+": "+e.getMessage()+']'));
	}

	public static boolean isEqual(Object a, Object b) {
		return a==null ? (b==null ? true : false) : (b==null ? false : a.equals(b));
	}
	
	public static DateFormat getDateFormat() {
		return dateFormat ;
	}

	public static boolean isEmail(String email) {
		return StringUtils.isNotBlank(email) && email.matches(REG_EXP_EMAIL);
	}
	
	public static void main(String...strings) { // XXX
//		System.out.println(isEmail("xhh@dd.jj"));
		
	}
	
}
